package org.csource.quickstart.processor.group;

import org.csource.quickstart.FResult;
import org.csource.quickstart.processor.AbstractFileProcessor;
import org.csource.quickstart.processor.FileUploadProcessor;
import org.csource.quickstart.processor.ProcessorChannel;
import org.csource.quickstart.request.UploadRequest;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONObject;
import com.google.common.util.concurrent.FutureCallback;


public abstract class AbstractChannelProcessor extends AbstractFileProcessor implements FileUploadProcessor{
  
  public static String KEY = "PUBLIC";
  
  private ThreadLocal<FResult<JSONObject>> proccessResult = new ThreadLocal<FResult<JSONObject>>();
  
  protected String getProcessorChannel() {
    ProcessorChannel processorGroup = this.getClass().getAnnotation(ProcessorChannel.class);
    if (processorGroup != null) {
      return processorGroup.channel();
    }else{
      return KEY;
    }
  }
  
  @Override
  public boolean care(UploadRequest uploadRequest) {
    return getProcessorChannel().equals(uploadRequest.getChannel());
  }
  
  @Override
  @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
  public FResult<JSONObject> process(UploadRequest request) throws Exception {
    FResult<JSONObject> result = null;
    FileUploadProcessor process = this;
    try {
      do{
        /**
         * 本次的处理结果
         * 请求参数对象
         * 上一次的处理结果
         */
        result = ((AbstractChannelProcessor)process).doProcess(request,getFutureCallback());
      }while (this.nextProcessor!=null && ((process = ((AbstractChannelProcessor)process).nextProcessor)!=null));
    } finally {
      proccessResult.remove();
    }
    return result;
  }
  
  protected abstract FResult<JSONObject> doProcess(UploadRequest request,FutureCallback<Object> response);
  
  protected abstract FutureCallback<Object> getFutureCallback();
  
  public FileUploadProcessor nextProcessor;
  
}
